<?php

namespace System\Core;

use System\Core\Config;

class Log implements Logger
{
    private static $instance;
    private $logPath;
    private $channels = [];
    private $defaultChannel;

    // 日志级别常量
    const DEBUG     = 100;
    const INFO      = 200;
    const NOTICE    = 250;
    const WARNING   = 300;
    const ERROR     = 400;
    const CRITICAL  = 500;
    const ALERT     = 550;
    const EMERGENCY = 600;

    // 日志级别名称映射
    protected static $levels = [
        self::DEBUG     => 'DEBUG',
        self::INFO      => 'INFO',
        self::NOTICE    => 'NOTICE',
        self::WARNING   => 'WARNING',
        self::ERROR     => 'ERROR',
        self::CRITICAL  => 'CRITICAL',
        self::ALERT     => 'ALERT',
        self::EMERGENCY => 'EMERGENCY',
    ];

    private function __construct()
    {
        $this->logPath = BASE_PATH . '/storage/logs/';

        // 确保日志目录存在
        if (!is_dir($this->logPath)) {
            mkdir($this->logPath, 0755, true);
        }

        // 加载日志配置
        $this->loadConfig();
    }

    public static function getInstance()
    {
        if (!self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function loadConfig()
    {
        // 加载日志配置文件
        $config = Config::get('logging', []);

        // 默认配置
        $defaultConfig = [
            'default' => 'single',
            'channels' => [
                'single' => [
                    'driver' => 'single',
                    'path' => $this->logPath . 'app.log',
                    'level' => self::DEBUG,
                ],
                'daily' => [
                    'driver' => 'daily',
                    'path' => $this->logPath . 'app.log',
                    'level' => self::DEBUG,
                    'days' => 7,
                ],
                'errorlog' => [
                    'driver' => 'errorlog',
                    'level' => self::ERROR,
                ],
            ],
        ];

        $config = array_merge($defaultConfig, $config);
        $this->defaultChannel = $config['default'];
        $this->channels = $config['channels'];
    }

    public function channel($name = null)
    {
        $channel = $name ?: $this->defaultChannel;

        if (!isset($this->channels[$channel])) {
            throw new \InvalidArgumentException("Log channel [{$channel}] is not defined.");
        }

        return $this->getChannelDriver($this->channels[$channel]);
    }

    private function getChannelDriver($config)
    {
        $driver = $config['driver'] ?? 'single';

        switch ($driver) {
            case 'single':
                return new LogHandlers\SingleFileHandler(
                    $config['path'] ?? $this->logPath . 'app.log',
                    $config['level'] ?? self::DEBUG
                );
            case 'daily':
                return new LogHandlers\DailyFileHandler(
                    $config['path'] ?? $this->logPath . 'app.log',
                    $config['days'] ?? 7,
                    $config['level'] ?? self::DEBUG
                );
            case 'errorlog':
                return new LogHandlers\ErrorLogHandler(
                    $config['level'] ?? self::ERROR
                );
            default:
                throw new \InvalidArgumentException("Unsupported log driver: {$driver}");
        }
    }

    public function log($level, $message, array $context = []) {
        // 修复：调用handle方法而不是log方法
        $this->channel()->handle($level, $message, $context);
    }

    public function debug($message, array $context = [])
    {
        $this->log(self::DEBUG, $message, $context);
    }

    public function info($message, array $context = [])
    {
        $this->log(self::INFO, $message, $context);
    }

    public function notice($message, array $context = [])
    {
        $this->log(self::NOTICE, $message, $context);
    }

    public function warning($message, array $context = [])
    {
        $this->log(self::WARNING, $message, $context);
    }

    public function error($message, array $context = [])
    {
        $this->log(self::ERROR, $message, $context);
    }

    public function critical($message, array $context = [])
    {
        $this->log(self::CRITICAL, $message, $context);
    }

    public function alert($message, array $context = [])
    {
        $this->log(self::ALERT, $message, $context);
    }

    public function emergency($message, array $context = [])
    {
        $this->log(self::EMERGENCY, $message, $context);
    }

    public static function getLevelName($level)
    {
        return self::$levels[$level] ?? 'UNKNOWN';
    }
}
